#include "led.h"
#include "soft_timer.h"

struct LED_PERIOD_T
{
  uint16 status;
  uint16 ms;
};

typedef struct LED_PERIOD_T LED_PERIOD_T;

struct LED_T
{
  const LED_PERIOD_T* periods;
  uint16 count;
  uint16 current_index;
};

static struct LED_T g_led;

void led_init(void)
{
  P1DIR |= BIT4;
}

void led_on_timer()
{
  if (g_led.periods != NULL && g_led.current_index < g_led.count)
  {
    const LED_PERIOD_T* p = NULL;
    soft_timer_stop(TIMER_ID_FLASH_LED);
    if (++g_led.current_index >= g_led.count)
      g_led.current_index = 0;
    p = &g_led.periods[g_led.current_index];
    led_set(p->status);
    soft_timer_start(TIMER_ID_FLASH_LED, timer_ms_to_tick((uint32)p->ms), 0, led_on_timer);
  }
}

void led_start_loop(const LED_PERIOD_T* periods, uint16 count)
{
  g_led.periods = periods;
  g_led.count = count;
  g_led.current_index = 0;
  soft_timer_stop(TIMER_ID_FLASH_LED);
  if (g_led.current_index < g_led.count)
  {
    uint32 interval = timer_ms_to_tick((uint32)g_led.periods[g_led.current_index].ms);
    led_set(g_led.periods[g_led.current_index].status);
    soft_timer_start(TIMER_ID_FLASH_LED, interval, 0, led_on_timer);
  }
}


/* Normal state, loop:
 * 0.1s on
 * 2s off
 */
void led_state_normal(void)
{
  static LED_PERIOD_T periods[] = {{1, 100}, {0, 2000}};
  led_start_loop(periods, 2);
}

/*
 * Collecting state, loop: 
 * 0.1s on 
 * 1s off 
 */
void led_state_collecting(void)
{
  static LED_PERIOD_T periods[] = {{1, 100}, {0, 1000}};
  led_start_loop(periods, 2);
}

/*
 * Offline state, loop: 
 * 0.1s on 
 * 10s off 
 */
void led_state_offline(void)
{
  static LED_PERIOD_T periods[] = {{1, 100}, {0, 10000}};
  led_start_loop(periods, 2);
}

/*
 * debugging mode, loop:
 * always on
 */
void led_state_debugging(void)
{
  static LED_PERIOD_T periods[] = {{1, 10000}};
  led_start_loop(periods, 1);
}

/*
 * always off
 */
void led_state_communicating(void)
{
  static LED_PERIOD_T periods[] = {{0, 10000}};
  led_start_loop(periods, 1);
}

/*
 * Abnormal state, loop:
 * 0.1s on 
 * 0.3s off 
 */
void led_state_abnormal(void)
{
  static LED_PERIOD_T periods[] = {{1, 100}, {0, 300}};
  led_start_loop(periods, 2);
}
